#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/10/21 9:20
# @Author  : zy
# @File    : word_tpl.py
"""

以模板的生成 word文件

"""

from units import *


class PointRecords:
    """
        有害垃圾清运记录
        1.通过点位查询对应的点位信息
        2.点位信息求 _id 对应查询 记录中 fk=_id 的清运记录
        3.随机生成清运记录 对应的时间对象之间（每月1次）
        4.清运记录有真有假混合生成
        5.输出 给数据库，csv json  给模板文件生成word

    """

    def __init__(self, start: datetime, end: datetime):
        self.start = start
        self.end = end

        self.point_json = {}
        self.records = []
        self.summary = []

    # 从真实记录中获取年月的列表
    def __find_year_month_from_really_records(self) -> list[tuple]:
        return [(r['datetime'].year, r['datetime'].month) for r in self.records]

    # 起始时间与终止时间中间月份列表
    def __date_range(self) -> list[tuple]:
        return DATETIME.get_month_range(self.start, self.end)

    @property
    def total(self) -> float | int:
        if self.summary:
            t = sum([s['w_total'] for s in self.summary])
            return t
        else:
            return 0

    # 封装获取点位字典的方法
    def get_point_data(self, fn, name=None):
        if fn:
            self.point_json = fn(name)  # 从数据查询函数返回dict

        else:
            self.point_json = {
                '_id': 'p-1001',
                'custom': '旺泉街道',
                'area_name': '悦君家园',
                'point_name': '悦君家园小区西门',
                'address': '北京市顺义区西外街19号靠近当代北辰悦MOMA',
                'point_no': '1#',
                'long': 116.6413128,
                'lat': 40.1439299,
                'unit': '中海悦君家园管理处',
                'manager': '王海朋',
                'tel': '13387346013',
                'notice': '小区西门，车不好进',
                'point_img': ['pic1......', 'pic2.....'],
            }
        return self

    # 根据输入日期对象，求真实的数据
    def really_records(self, fn):
        if fn:
            fk = self.point_json.get('_id')  # 获取fk
            start, end = DATETIME.date_to_datetime(self.start), DATETIME.date_to_datetime(self.end)  # 日期对象强制转为datetime
            self.records = fn(fk, start, end)  # 数据查询函数 返回list

            for _idx, _one in enumerate(self.records, start=1):
                _one['date'] = datetime.strftime(_one['datetime'], '%Y/%m/%d')  # 增加日期
                _one['time'] = datetime.strftime(_one['datetime'], '%H:%M')  # 增加时间
                _one['is_really'] = 1  # 真
                _sum = {
                    'idx': _idx,
                    'datetime': _one.get('datetime'),
                    'date': _one.get('date'),
                    'time': _one.get('time'),
                    'w_total': _one.get('w_total'),
                    'is_really': 1
                }
                self.summary.append(_sum)

        return self

    @staticmethod  # 随机时间对象
    def __rnd_datetime(year, month):
        _d = random.randint(10, 27)
        _hh = random.randint(6, 22)
        _mm = random.randint(0, 59)
        return datetime(year, month, _d, _hh, _mm, 0)

    # 单月随机记录
    def rnd_one_month_record(self, year, month) -> dict:
        if self.point_json:
            fk = self.point_json.get('_id')
        else:
            fk = 'tst'
        # 处理datetime 对象
        __dt = self.__rnd_datetime(year, month)  # datetime.datetime(2024, 1, 1, 17, 21)
        __date: str = __dt.strftime('%Y/%m/%d')
        __time: str = __dt.strftime('%H:%M')
        __weight: dict = {f"w{i}": random.randint(10, 20) for i in range(1, 9)}
        __w_total = sum(__weight.values())

        # 随机重量记录
        __rec = {
            '_id': CHART.uid_key(),
            'fk': fk,
            'datetime': __dt,
            'date': __date,
            'time': __time,
            'f_pic': ['图片1', '图片2'],
            'b_pic': ['图片1', '图片2'],
            'w_total': __w_total,
            'is_really': 0
        }
        __rec.update(__weight)

        return __rec

    # 随机记录 月范围
    def rnd_records(self):
        _idx = 1
        _range: list[tuple] = self.__date_range()

        if _range:
            for year, month in _range:
                _one = self.rnd_one_month_record(year, month)
                _sum = {
                    'idx': _idx,  # 增加处理具有真实数据的情况（放在一起按时间顺序排列）
                    'datetime': _one.get('datetime'),
                    'date': _one.get('date'),
                    'time': _one.get('time'),
                    'w_total': _one.get('w_total'),
                    'is_really': 0
                }

                self.records.append(_one)
                self.summary.append(_sum)

                _idx += 1

            return self
        else:
            raise "日期写反了"

    # 随机记录 月范围
    def rnd_records_2(self):
        # 增加处理 真实记录中存在相同月份的数据（遇到相同月份的真实数据，追加）
        if not self.records:

            return self.rnd_records()

        else:

            _lst = self.__find_year_month_from_really_records()  # 数据库中真实存在数据的(年,月) 元组列表

            _idx = 1
            _range: list[tuple] = self.__date_range()

            if _range:
                _filter = filter(lambda x: x not in _lst, _range)
                _ = list(_filter)

                for year, month in _:
                    _one = self.rnd_one_month_record(year, month)
                    _sum = {
                        'idx': _idx,  # 增加处理具有真实数据的情况（放在一起按时间顺序排列）
                        'datetime': _one.get('datetime'),
                        'date': _one.get('date'),
                        'time': _one.get('time'),
                        'w_total': _one.get('w_total'),
                        'is_really': 0
                    }

                    self.records.append(_one)
                    self.summary.append(_sum)

                    _idx += 1

                # 数据按时间排序
                self.records = sorted(self.records, key=lambda r: datetime.strftime(r['datetime'], '%Y-%m-%d %H:%M'))
                self.summary = sorted(self.summary, key=lambda r: datetime.strftime(r['datetime'], '%Y-%m-%d %H:%M'))

                for idx, item in enumerate(self.summary, 1):
                    item['idx'] = idx

                return self
            else:
                raise "日期写反了"

    # 数据输出
    def to_word_tpl(self):
        self.point_json.update({
            'records': self.records,
            'summary': self.summary,
            'total': self.total
        })
        return self.point_json

    def to_json_file(self):
        # 把record里的datetime对象去掉，保持可序列化的数据
        __rec = self.to_jsondb()
        self.point_json.update({
            'records': __rec,
            'summary': self.summary,
            'total': self.total
        })

        return self.point_json

    def to_jsondb(self):
        __rec = self.records
        for __r in __rec:
            __r.pop('datetime')
        return __rec

    def to_mongodb(self):
        __rec = self.records

        for __r in __rec:
            __r.pop('date')
            __r.pop('time')

        return __rec


# 生成有害垃圾点位记录
def point_record_docx(start: datetime | date, end: datetime | date, fn1=None, fn2=None, point_name=None) -> dict:
    """
        记录数据
    :param fn2: 获取真实记录的方法
    :param fn1: 获取point 数据的方法
    :param point_name:点位名称
    :param end:
    :param start:
    :return: dict

    """

    _p = (
        PointRecords(start, end)
            .get_point_data(fn1, point_name)  # 获取point 数据
            .really_records(fn2)  # 获取真实记录
            .rnd_records_2()  # 随机记录
    )

    return _p.to_word_tpl()


def three_price_docx(json_=None) -> dict:
    if json_ is None:
        json_ = {
            'partA': '北京市顺义区马坡第一幼儿园',
            'start_date': '2024/11/1',
            'end_date': '2025/7/31',
            'three': [
                {
                    "name": "北京宏鑫汇能循环经济科技发展有限公司",
                    'address': '北京市顺义区南法信镇南卷村东200米',
                    'user': '刘鹏',
                    'tel': '010-69471928',
                    "signal_price": 500.00,
                },
                {
                    "name": "北京智分瓦力环境工程有限公司",
                    'address': '北京市顺义区后沙峪镇安福街6号1362室',
                    'user': '刘平',
                    'tel': '18511982023',
                    "signal_price": 580.00,
                },
                {
                    "name": "北京铨胜恒德再生资源有限公司",
                    'address': '北京市顺义区南彩镇俸伯村西（村委会西500米）',
                    'user': '王鹏辉',
                    'tel': '15010190271',
                    "signal_price": 650.00,
                },
            ]
        }

    start = datetime.strptime(json_['start_date'], "%Y/%m/%d")
    end = datetime.strptime(json_['end_date'], "%Y/%m/%d")

    service_date = f"{start.year}年{start.month}月{start.day}日至{end.year}年{end.month}月{end.day}日"
    months = DATETIME.month_diff(start, end)  # 月差
    nums = 1
    json_.update({'service_date': service_date, 'months': months})
    for itm in json_['three']:
        price = itm['signal_price'] * months * nums
        itm.update({
            'service_date': service_date,
            'months': f"{months}",
            'nums': f"{nums}",
            'signal_price': f"{itm['signal_price']:.2f}",
            'price': f"{price:.2f}",
            'up_price': CHART.rmb_upper(price),
            'sign_date': '2024/10/8'
        })

    return json_


# 生成合同需要的数据
def contract_docx(json_=None) -> dict:
    if json_ is None:
        json_ = {
            'partA': {
                'name': '北京市顺义区马坡第一幼儿园',
                'tax': '',
                'bank': '',
                'account': '',
                'tel': '',
                'address': '',
            },
            'partB': {
                'name': '北京宏鑫汇能循环经济科技发展有限公司',
                'tax': '911101131025153202',
                'bank': '北京农商银行顺义支行',
                'account': '0801000103000050438',
                'tel': '',
                'address': '北京市顺义区南法信镇南卷村东200米'
            },
            'service_local': '北京市顺义区马坡第一幼儿园',
            'signal_price': 500.00,
        }

    start = datetime.strptime(json_['start_date'], "%Y/%m/%d")
    end = datetime.strptime(json_['end_date'], "%Y/%m/%d")

    service_date = f"自【 {start.year} 】年【 {start.month} 】月【 {start.day} 】日起至【 {end.year} 】年【 {end.month} 】月【 {end.day} 】止"
    months = DATETIME.month_diff(start, end)  # 月差
    price = json_['signal_price'] * months
    up_price = CHART.rmb_upper(price)

    json_.update({
        'service_date': service_date,
        'signal_price': f"{json_['signal_price']:.2f}",
        'months': f"{months}",
        'price': f"{price:.2f}",
        'up_price': up_price
    })

    return json_


# 模拟生成数据csv
def _records_tst():
    _comps = [
        {
            "_id": "c-0006",
            "ABC": "顺商集团",
            "name": "北京顺义商业集团有限公司",
            "jur_person": "李浩",
            "address": "北京市顺义区仁和地区府前西街1号1幢6层",
            "tax": "91110113MA00DQ6D3C",
            "bank": "北京银行顺义支行",
            "account": "20000034428100016343054",
            "tel_1": "010-81487888",
            "relation": "有害垃圾-清运",
            "user": "孟远",
            "tel_2": "nan"
        },
        {
            "_id": "c-0007",
            "ABC": "旺泉街道",
            "name": "北京市顺义区旺泉街道办事处",
            "jur_person": '',
            "address": "北京市顺义区望泉北街1号",
            "tax": "1111011066841756XE",
            "bank": "工行北京中山街支行",
            "account": "0200041209200065590",
            "tel_1": "010-61409508",
            "relation": "有害垃圾-清运",
            "user": "马壮",
            "tel_2": "nan"
        },
    ]

    with open('../db/有害垃圾点位.json', mode='r', encoding='utf-8') as f:
        points = json.load(f)

    points = list(filter(lambda x: x['point'] is not None, points))
    sample = random.sample(points, 35)  # 随机选取点位名称35个
    for point in sample:
        dt1 = datetime.strptime('2024-11-1', "%Y-%m-%d")
        dt2 = datetime.strptime(f'2025-{random.randint(1, 10)}-28', "%Y-%m-%d")

        p = PointRecords(dt1, dt2)
        p.point_json = point  # point 数据
        p.rnd_records()  # 随机记录

        FILE.dict_to_csv('../db/清运记录.csv', p.to_mongodb())  # 存储到文件中


def _run_three_price():
    tpl = r'..\tpl\模版_三方比价_有害垃圾清运.docx'
    context = three_price_docx()
    filename = f"../tmp/三方比价_有害垃圾_{context.get('partA')}.docx"
    FILE.word_file(tpl, context, filename)


def _run_contract():
    tpl = r'..\tpl\模版_服务合同_有害垃圾委托清运.docx'
    context: dict = contract_docx()
    filename = f"../tmp/服务合同_有害垃圾_{context['partA'].get('name')}.docx"
    FILE.word_file(tpl, context, filename)


def _run_clear_records():
    def _fn1(name: str):
        _df = pd.read_json('../db/有害垃圾点位.json')
        _df.to_dict()
        _df_one = _df[_df['point'] == name]

        return _df_one.to_dict(orient="records")[0]

    def _fn2(fk, start, end):
        _df = pd.read_csv('../db/清运记录.csv')
        _df = _df[_df['fk'] == fk]
        _df['datetime'] = pd.to_datetime(_df['datetime'], format='%Y-%m-%d %H:%M:%S')
        _df = _df[(_df['datetime'] >= start) & (_df['datetime'] <= end)]
        return _df.to_dict(orient='records')

    dt1 = datetime.strptime('2024-11-1', "%Y-%m-%d")
    dt2 = datetime.strptime('2025-10-30', "%Y-%m-%d")

    tpl = r'..\tpl\模板_记录_有害垃圾清运.docx'
    context = point_record_docx(fn1=_fn1, fn2=_fn2, start=dt1, end=dt2, point_name='顺商国泰大厦店')
    print(context)
    filename = f"res/记录_有害垃圾清运_{context.get('_id')}.docx"

    FILE.word_file(tpl, context, filename)


if __name__ == '__main__':
    # _run_three_price()
    # _run_contract()
    _run_clear_records()

    # _records_tst()

    pass
